package com.thinkit.bigdata.web.service.impl.sys;

import com.google.common.base.Strings;
import com.thinkit.bigdata.core.feature.orm.mybatis.Page;
import com.thinkit.bigdata.core.util.*;
import com.thinkit.bigdata.core.util.excel.XlsUtil;
import com.thinkit.bigdata.core.util.ip.IPUtil;
import com.thinkit.bigdata.web.coremet.SystemStatic;
import com.thinkit.bigdata.web.dao.sys.*;
import com.thinkit.bigdata.web.model.BaseEntity;
import com.thinkit.bigdata.web.model.config.SysArea;
import com.thinkit.bigdata.web.model.result.Constants;
import com.thinkit.bigdata.web.model.result.HtmlResult;
import com.thinkit.bigdata.web.model.sec.*;
import com.thinkit.bigdata.web.model.sys.*;
import com.thinkit.bigdata.web.service.config.AreaService;
import com.thinkit.bigdata.web.service.sec.GroupService;
import com.thinkit.bigdata.web.service.sec.UserService;
import com.thinkit.bigdata.web.service.sys.SysApprovalConfigService;
import com.thinkit.bigdata.web.service.sys.SysApprovalTaskService;
import com.thinkit.bigdata.web.service.sys.SysConfigService;
import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.beanutils.ConvertUtils;
import org.apache.commons.beanutils.converters.DateConverter;
import org.apache.log4j.Logger;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.session.Session;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.util.*;

@Service
public class SysApprovalTaskServiceImpl implements SysApprovalTaskService {

    private static Logger logger = Logger.getLogger(SysApprovalTaskServiceImpl.class);

    @Resource
    private AreaService areaService;

    @Resource
    private UserService userService;

    @Resource
    protected GroupService groupService;

    @Resource
    private SysApprovalTaskMapper taskMapper;

    @Resource
    private SysApprovalDataMapper dataMapper;

    @Resource
    private SysExportUserParamMapper userParamMapper;

    @Resource
    private SysApprovalRecordMapper approvalRecordMapper;

    @Resource
    private SysExportRecordMapper exportRecordMapper;

    @Resource
    private SysApprovalConfigService configService;

    @Resource
    private SysConfigService sysConfigService;

    @Resource
    private ProjectPubMet pubMet;

    @Override
    public HtmlResult exportTaskSearch(SysApprovalTaskSearch task) throws InvocationTargetException, IllegalAccessException {
        Map<String, Object> map = new HashMap<>();
        if (!Strings.isNullOrEmpty(task.getDatacode())) {
            map.put("dataCode", task.getDatacode());
        }
        if (task.getApprovalstatus() != null) {
            map.put("approvalStatus", task.getApprovalstatus());
        }
        if (task.getLinenumber() != null) {
            map.put("linenumber", task.getLinenumber());
        }
        if (!Strings.isNullOrEmpty(task.getLastapprovaltimeBegin())) {
            map.put("lastApprovalTimeBegin", task.getLastapprovaltimeBegin());
        }
        if (!Strings.isNullOrEmpty(task.getLastapprovaltimeEnd())) {
            map.put("lastApprovalTimeEnd", task.getLastapprovaltimeEnd());
        }
        if (!Strings.isNullOrEmpty(task.getCreatetimeBegin())) {
            map.put("createTimeBegin", task.getCreatetimeBegin());
        }
        if (!Strings.isNullOrEmpty(task.getCreatetimeEnd())) {
            map.put("createTimeEnd", task.getCreatetimeEnd());
        }
        User userInfo = (User) SecurityUtils.getSubject().getSession().getAttribute(Constants.SESSION_USER_INFO);
        map.put("createUserId", userInfo.getId());
        User user = userService.getUserByPK(userInfo.getId());
        StringBuilder roleIds = new StringBuilder();
        int i = 0;
        //查看待审批角色
        for (Long roleId : user.getRoleidlist()) {
            if (i == user.getRoleidlist().size() - 1) {
                roleIds.append(roleId);
            } else {
                roleIds.append(roleId).append(",");
            }
            i++;
        }
        if ("".equals(roleIds.toString())) {
            return HtmlResult.success(new ArrayList<>(), 0);
        }
        if (task.getToapprovalroleid() != null) {
            map.put("toApprovalRoleNow", task.getToapprovalroleid());
        } else {
            map.put("toApprovalRole", Arrays.asList(roleIds.toString().split(",")));
        }
        Page<SysApprovalTask> page = new Page<>(task.getPageNum() + 1, task.getPageSize());
        List<SysApprovalTask> taskList = taskMapper.selectByExampleMap(page, map);
        List<SysApprovalTaskDto> dtos = new ArrayList<>();
        for (SysApprovalTask task1 : taskList) {
            SysApprovalTaskDto dto = new SysApprovalTaskDto();
            ConvertUtils.register(new DateConverter(null), java.util.Date.class);
            BeanUtils.copyProperties(dto, task1);
            if (task1.getCreateuserid().toString().equals(user.getId().toString())
                    && task1.getApprovalstatus() == BaseEntity.APPROVAL_STATUS_YES) {//todo任务创建人为当前用户，并审批通过，则为下载按钮
                dto.setButtonType("download");
            } else if (user.getRoleidlist().contains(task1.getToapprovalroleid())) {//todo任务当前审批人为当前用户，则为审批按钮
                dto.setButtonType("approval");
            } else {
                dto.setButtonType("show");
            }
            dto.setDatacodeName(dataMapper.selectByPrimaryKey(task1.getDatacode()).getDataname());
            SysExportUserParam param = userParamMapper.selectByPrimaryKey(task1.getId());
            if (param != null) {
                dto.setIsDel(param.getIsdel());
            }
            dtos.add(dto);
        }
        return HtmlResult.success(dtos, page.getTotalCount());
    }

    @Override
    public HtmlResult exportTaskParamSearch(Long id) {
        return HtmlResult.success(userParamMapper.selectByPrimaryKey(id));
    }

    @Override
    public HtmlResult addExportTask(HttpServletRequest request) {
        String code = request.getParameter("code");
        Session session = SecurityUtils.getSubject().getSession();
        User userInfo = (User) session.getAttribute(Constants.SESSION_USER_INFO);
        SysArea area = (SysArea) session.getAttribute("areaInfo");
        SysApprovalTask task = new SysApprovalTask();
        if (area != null) {
            task.setProvincecode(area.getCode());
        }
        task.setDatacode(code);
        task.setCreateuserid(userInfo.getId());
        task.setCreateuser(userInfo.getUsername());
        task.setCreatetime(new Date());
        task.setApprovalstatus(BaseEntity.APPROVAL_STATUS_BEGIN);
        task.setNote("no");//todo备注字段，先用来做判断是否最后审批
        User user = userService.getUserByPK(userInfo.getId());
        List<SysApprovalConfigRel> rels = new ArrayList<>();
        SysRole sysRole = null;
        //查看待审批角色
        for (SysRole role : user.getRolelist()) {
            if (rels.isEmpty()) {//给角色有流程，就按照该角色走
                rels = configService.selectByCodeAndLine(code, role.getId());
                if (rels.isEmpty()) {
                    return HtmlResult.failure("您目前的角色不满足审批导出功能，请先联系管理员配置导出流程");
                }
                sysRole = role;
                task.setNote(rels.get(rels.size()-1).getApproleid().toString());//todo暂时先存储流程的最后审批角色id
            }
            if (rels.isEmpty()) {
                return HtmlResult.failure("您目前的角色不满足审批导出功能，请先联系管理员配置导出流程");
            }
        }
        if (rels.isEmpty()) {
            return HtmlResult.failure("当前登录用户没有角色信息，请先配置角色");
        }
        task.setToapprovalroleid(rels.get(0).getApproleid());
        task.setToapprovalrole(rels.get(0).getApprole());
        //流程标识
        task.setLinenumber(sysRole.getId());
        task.setLinenumbername(sysRole.getName());
        int addRes = taskMapper.insertSelective(task);
        if (addRes == 0) {
            return HtmlResult.failure("请求失败，请稍后再试或联系系统管理员！");
        }
        //添加导出条件纪录
        String areaId = request.getParameter("areaId");
        String groupId = request.getParameter("groupId");
        String seatGroup = request.getParameter("seatGroup");
        String account = request.getParameter("account");
        String userName = request.getParameter("userName");
        String realName = request.getParameter("realName");
        String status = request.getParameter("status");
        String fileContent = request.getParameter("fileContent");
        String fileContext = request.getParameter("fileContext");
        SysExportUserParam userParam = new SysExportUserParam();
        userParam.setUserid(userInfo.getId());
        userParam.setProvaltaskid(task.getId());
        if (!Strings.isNullOrEmpty(areaId) && !areaId.equals("9999")) {
            SysArea sysArea = areaService.selectByPrimaryKey(Integer.parseInt(areaId));
            userParam.setProvincecode(sysArea.getCode());
            userParam.setProvincename(sysArea.getArea());
        }
        if (!Strings.isNullOrEmpty(groupId)) {
            userParam.setGroupid(Long.parseLong(groupId));
            userParam.setSeatgroup(seatGroup);
        }
        if (!Strings.isNullOrEmpty(account)) {
            userParam.setAccount(account);
        }
        if (!Strings.isNullOrEmpty(userName)) {
            userParam.setUsername(userName);
        }
        if (!Strings.isNullOrEmpty(realName)) {
            userParam.setRealname(realName);
        }
        if (status != null) {
            userParam.setStatus(status);
        }
        userParam.setFilecontent(fileContent);
        userParam.setFilecontext(fileContext);
        userParam.setInputtime(new Date());
        userParam.setIsdel(BaseEntity.FILE_IS_DEL_NO);
        String fileName = "userMes_" + DateFormatUtil.getNowTime() + ".xls";
        String fileUrl = SystemStatic.SYSTEM_USER_PATH_EXPORT + fileName;
        userParam.setFilename(fileName);
        userParam.setFileurl(fileUrl);
        if (userParamMapper.insertSelective(userParam) == 0) {
            taskMapper.deleteByPrimaryKey(task.getId());
            return HtmlResult.failure("请求失败，请稍后再试或联系系统管理员！");
        }
        return HtmlResult.success("已提交审批，请到‘审批结果页面‘查看审批进度");
    }

    @Override
    public HtmlResult updateExportTask(Long id, int status, String note, HttpServletResponse response) {
        String EXPORT_LOG_MES = "【审核操作】";
        User userInfo = (User) SecurityUtils.getSubject().getSession().getAttribute(Constants.SESSION_USER_INFO);
        Date date = new Date();
        SysApprovalTask task = taskMapper.selectByPrimaryKey(id);
        if (task == null) {
            return HtmlResult.failure(EXPORT_LOG_MES + "任务已被删除");
        }
        int oldstatus = task.getApprovalstatus();
        //审批不通过
        //修改状态，最后审批人，最后审批时间，待审批角色至空
        if (status == BaseEntity.APPROVAL_STATUS_NO) {
            logger.info(EXPORT_LOG_MES + "审批不通过");
            task.setLastapprovaluser(userInfo.getId());
            task.setLastapprovalnote(note);
            task.setLastapprovaltime(date);
            task.setToapprovalroleid(null);
            task.setToapprovalrole(null);
            task.setApprovalstatus(status);
            task.setNote(null);
            logger.info(EXPORT_LOG_MES + "将文件名称和路径删除");
            SysExportUserParam userParam = userParamMapper.selectByPrimaryKey(id);
            userParam.setFileurl(null);
            userParam.setFilename(null);
            userParamMapper.updateByPrimaryKey(userParam);
        }
        //审批通过
        else {
            logger.info(EXPORT_LOG_MES + "审批通过");
            List<SysApprovalConfigRel> rels = configService.selectByCodeAndLine(task.getDatacode(), task.getLinenumber());
            if (rels.isEmpty()) {
                return HtmlResult.failure("批复失败，没有相关的审批流程配置，请联系系统开发人员！");
            }
            //判断是否流程已经走完，走完了，修改状态，最后审批人，最后审批时间，待审批角色至空
            logger.info(EXPORT_LOG_MES + "判断是否流程已经走完");
            User user = userService.getUserByPK(userInfo.getId());
            //当前审批人员角色id与流程中最后审批角色id一致，该流程已经走完了
            if (user.getRoleidlist().contains(Long.parseLong(task.getNote()))) {//note装的是最后审批角色id
                logger.info(EXPORT_LOG_MES + "当前审批人员角色id与流程中最后审批角色id一致，该流程已经走完了");
                task.setLastapprovaluser(user.getId());
                task.setLastapprovalnote(note);
                task.setLastapprovaltime(date);
                task.setToapprovalroleid(null);
                task.setToapprovalrole(null);
                task.setNote(null);
                task.setApprovalstatus(BaseEntity.APPROVAL_STATUS_YES);
                //todo自动生成文件，然后放置到指定路径下
                SysExportUserParam param = userParamMapper.selectByPrimaryKey(task.getId());
                try {
                    this.downloadFileByTaskId(EXPORT_LOG_MES, param, response);
                    //上传到ftp
                    //登陆ftp
                    FtpUtil ftpUtil = pubMet.getFtpUtil();
                    File localFile = new File(param.getFileurl());
                    //创建ftp路径
                    if (!ftpUtil.createDirs(SystemStatic.FTP_PATH_EXPORT_APPROVAL)) {
                        FileUtil.deleteFile(localFile);
                        throw new RuntimeException();
                    }
                    //文件上传ftp
                    if (!ftpUtil.upload(localFile, SystemStatic.FTP_PATH_EXPORT_APPROVAL)) {
                        throw new RuntimeException();
                    }
                    //关闭ftp链接
                    ftpUtil.disconnect();
                    //ftp上传成功，删除本地文件
                    FileUtil.deleteFile(localFile);
                    param.setFileurl(SystemStatic.FTP_PATH_EXPORT_APPROVAL + localFile.getName());
                } catch (Exception e) {
                    logger.info(EXPORT_LOG_MES + "文件生成失败");
                    //todo 文件生成状态记录
                }
                param.setFinishtime(new Date());
                userParamMapper.updateByPrimaryKey(param);
            }
            //没有走完，修改待审批角色未下一个角色
            else {
                logger.info(EXPORT_LOG_MES + "没有走完，修改待审批角色未下一个角色");
                task.setToapprovalroleid(getIndexByObject(rels, user.getRoleidlist().get(0)).getApproleid());
                task.setToapprovalrole(getIndexByObject(rels, user.getRoleidlist().get(0)).getApprole());
                task.setApprovalstatus(BaseEntity.APPROVAL_STATUS_ING);
            }
        }
        if (taskMapper.updateByPrimaryKey(task) == 0) {
            return HtmlResult.failure("批复失败，请联系运维工程师！");
        }
        //记录审批记录
        SysApprovalRecord record = new SysApprovalRecord();
        record.setApprovaltaskid(task.getId());
        record.setApprovaluser(userInfo.getId());
        record.setApprovaltime(date);
        record.setApprovalnote(note);
        record.setNewstatus(task.getApprovalstatus());
        record.setOldstatus(oldstatus);
        record.setApprovalip(IPUtil.getLocalIP());
        approvalRecordMapper.insertSelective(record);
        return HtmlResult.success("批复成功！");
    }

    @Override
    public void downloadFileByTaskId(String logTxt, SysExportUserParam param, HttpServletResponse response) throws IOException {
        //todo自动生成文件，然后放置到指定路径下
        String fileContext = param.getFilecontent();
        logger.info(logTxt + "fileContext = " + fileContext);
        String fileName = param.getFilename();
        logger.info(logTxt + "fileName = " + fileName);
        String fileUrl = param.getFileurl();
        logger.info(logTxt + "fileUrl = " + fileUrl);
        //获取用户导出用户信息
        List<Map<String, Object>> userList = getExportUserList(param);
        XlsUtil.exportUser(userList, param.getFilecontent(), param.getFileurl(), response, "mi");
    }

    @Override
    public HtmlResult exportFileTask(Long id, HttpServletResponse response) {
        User userInfo = (User) SecurityUtils.getSubject().getSession().getAttribute(Constants.SESSION_USER_INFO);
        Date date = new Date();
        //判断文件是否过期
        SysExportUserParam param = userParamMapper.selectByPrimaryKey(id);
        //过期天数
        int textMaxHour = Integer.parseInt(sysConfigService.sysConfigGetByPK(Constants.TEXT_MAX_HOUR).getValue());
        Date invalidTime = DateFormatUtil.addMinute(param.getFinishtime(), (textMaxHour * 60));
        if (DateFormatUtil.intervalSecond(invalidTime,  date) > 0) {
            return HtmlResult.failure("文件已经过期！");
        }
        SysApprovalTask task = taskMapper.selectByPrimaryKey(id);
        //修改任务字段
        task.setLastexportuser(userInfo.getId());
        task.setLastexporttime(date);
        task.setLastexportip(IPUtil.getLocalIP());
        if (taskMapper.updateByPrimaryKey(task) == 0) {
            return HtmlResult.failure("文件下载成功，记录失败，请联系运维工程师！");
        }
        SysExportRecord record = new SysExportRecord();
        record.setExportuser(userInfo.getId());
        record.setApprovaltaskid(task.getId());
        record.setExporttime(date);
        record.setExportip(task.getLastexportip());
        exportRecordMapper.insertSelective(record);
        return HtmlResult.success("下载成功！");
    }

    @Override
    public HtmlResult delExportTask(String ids) {
        for (String id : ids.split(",")) {
            if (userParamMapper.deleteByPrimaryKey(Long.parseLong(id)) == 0) {
                return HtmlResult.failure("删除失败！");
            }
            if (taskMapper.deleteByPrimaryKey(Long.parseLong(id)) == 0) {
                return HtmlResult.failure("删除失败！");
            }
        }
        return HtmlResult.success("删除成功");
    }

    //获取下一个审批角色
    private static SysApprovalConfigRel getIndexByObject(List<SysApprovalConfigRel> rels, Long obj) {
        int index = 0;
        for (int i = 0; i < rels.size(); i++) {
            if (rels.get(i).getApproleid().toString().equals(obj.toString())) {
                index = i+1;
            }
        }
        return rels.get(index);
    }

    private List<Map<String, Object>> getExportUserList(SysExportUserParam param) {
        UserExample example = new UserExample();
        UserExample.Criteria criteria = example.createCriteria();
        // 其他查询条件
        String areaId = null; //省份id
        if (!Strings.isNullOrEmpty(param.getProvincecode())) {
            areaId = areaService.selectByPrimaryCode(param.getProvincecode()).getId().toString();

        }
        Long groupId = param.getGroupid();   //组织机构id
        String account = param.getAccount();   //工号
        String userName = param.getUsername(); //用户名
        String realName = param.getRealname(); //真实姓名
        User authUserInfo = userService.getUserByPK(param.getUserid());
        User user = userService.selectByUsername(authUserInfo.getUsername());
        // 限制超管和省份人员不能查询出自己进行操作 只有集团人员能查询出来自己
        if (user.getGroupid() == null || user.getGroup().getAreaid().longValue() != Constants.GROUP_AREAID.longValue()) {
            // 如果用户所属机构为null(说明为admin) 用户所属省份id不为集团id 则限制用户不能查询出来自己
            criteria.andIdNotEqualTo(user.getId());
        }
        // 限制用户不能查询出来admin 如果groupid不为空 肯定查询不出来admin 如果为空 则设置groupid不能为空（admin没有groupid）
        if (groupId == null) {
            criteria.andGroupidIsNotNull();
            // 当groupId为空 判断areaid 获取当前登录用户允许访问的组织机构范围
            List<Long> subGroupIdList = userService.getAllSubGroupId(areaId);
            if (!subGroupIdList.isEmpty()) {
                criteria.andGroupidIn(subGroupIdList);
            }
        }
        if (groupId != null && groupId.toString().matches("\\d*")) {
            // 根据groupId递归获取该部门下所有部门id
            List<Long> groupIdList = new ArrayList<>();
            groupIdList.add(groupId);
            recursionGroupId(groupId, groupIdList);
            criteria.andGroupidIn(groupIdList);
        }
        if (StringUtil.isNotEmpty(account)) {
            criteria.andAccountLike("%" + account + "%");
        }
        if (StringUtil.isNotEmpty(userName)) {
            criteria.andUsernameLike("%" + userName + "%");
        }
        if (StringUtil.isNotEmpty(realName)) {
            criteria.andRealnameLike("%" + realName + "%");
        }
        if (StringUtil.isNotEmpty(param.getStatus())) {
            String[] isDeleteArray = param.getStatus().split(",");
            List<Integer> isDeleteList = new ArrayList<>();
            for (String s : isDeleteArray) {
                try {
                    isDeleteList.add(Integer.valueOf(s));
                } catch (NumberFormatException e) {
                    e.printStackTrace();
                }
            }
            criteria.andIsdeleteIn(isDeleteList);
        }
        return userService.selectUserDataToExport(example);
    }

    /**
     * 递归获取某部门下所有机构id
     *
     */
    private void recursionGroupId(Long groupId, List<Long> groupIdList) {
        SysGroupExample groupExample = new SysGroupExample();
        groupExample.createCriteria().andParentidEqualTo(groupId);
        List<SysGroup> groupList = groupService.selectByExample(groupExample);
        for (SysGroup group : groupList) {
            groupIdList.add(group.getId());
            recursionGroupId(group.getId(), groupIdList);
        }
    }
}
